/* @flow */

import config from '../config'
import { initUse } from './use'
import { initMixin } from './mixin'
import { initExtend } from './extend'
import { initAssetRegisters } from './assets'
import { set, del } from '../observer/index'
import { ASSET_TYPES } from 'shared/constants'
import builtInComponents from '../components/index'
import { observe } from 'core/observer/index'

import {
  warn,
  extend,
  nextTick,
  mergeOptions,
  defineReactive
} from '../util/index'

export function initGlobalAPI (Vue: GlobalAPI) {
  // config
  const configDef = {}
  configDef.get = () => config
  if (process.env.NODE_ENV !== 'production') {
    configDef.set = () => {
      warn(
        'Do not replace the Vue.config object, set individual fields instead.'
      )
    }
  }
  Object.defineProperty(Vue, 'config', configDef)

  // exposed util methods.
  // NOTE: these are not considered part of the public API - avoid relying on
  // them unless you are aware of the risk.
  // Vue.util 以及 util 下的四个方法都不被认为是公共API的一部分
  // 要避免依赖他们，但是你依然可以使用，只不过风险你要自己控制。
  // 并且，在官方文档上也并没有介绍这个全局API，所以能不用尽量不要用。
  Vue.util = {
    warn,
    extend,
    mergeOptions,
    defineReactive
  }

  // Vue的全局属性
  Vue.set = set
  Vue.delete = del
  Vue.nextTick = nextTick

  // 2.6 explicit observable API
  // 2.6 版本新增的 observable 方法，让一个对象可响应
  Vue.observable = <T> (obj: T): T => {
    observe(obj)
    return obj
  }

  // Vue.options 各种全局配置项
  // 通过Object.create(null)创建一个没有原型链的空对象
  Vue.options = Object.create(null)
  // ASSET_TYPES: ['component', 'directive', 'filter']，统一在这些配置项key后面增加s
  ASSET_TYPES.forEach(type => {
    Vue.options[type + 's'] = Object.create(null)
  })
  // this is used to identify the "base" constructor to extend all plain-object
  // components with in Weex's multi-instance scenarios.
  // 在Weex的多实例场景中，它用于标识“基本”构造函数以扩展所有纯对象组件。
  Vue.options._base = Vue

  // 将组件混合到目标对象中。builtInComponents中含有KeepAlive组件
  extend(Vue.options.components, builtInComponents)

  /*
    目前的Vue.config
    Vue.options = {
      components: {
        KeepAlive
      },
      directives: Object.create(null),
      filters: Object.create(null),
      _base: Vue
    }
  * */

  // 通过initUse方法定义，就是常用的Vue.use
  initUse(Vue)
  // 通过initMixin方法定义，全局API，Vue.mixin
  initMixin(Vue)
  // 通过initExtend方法定义，在Vue实例上增加了Vue.cid静态属性和Vue.extend方法
  initExtend(Vue)

  initAssetRegisters(Vue)
}
